﻿using System;
using System.Reflection;
using System.Runtime.Loader;

namespace xycn.framework.PluginManagement
{
    public class PluginLoadContext : AssemblyLoadContext
    {
        /// <summary>
        /// 插件本身的程序集
        /// </summary>
        public Assembly pluginAssembly = null;

        /// <summary>
        /// 插件名称
        /// </summary>
        public string pluginName = "";

        /// <summary>
        /// 用于保存默认运行环境程序集
        /// </summary>
        /*public Dictionary<string, Assembly> loadAssemblies =
            new Dictionary<string, Assembly>();*/

        /// <summary>
        /// 依赖库路径解析
        /// </summary>
        private AssemblyDependencyResolver _resolver;

        /// <summary>
        /// 初始化，并设置是否可回收为true；
        /// </summary>
        /// <param name="pluginPath"></param>
        public PluginLoadContext(string pluginPath) //: base(isCollectible : true)
        {
            _resolver = new AssemblyDependencyResolver(pluginPath);
        }

        /// <summary>
        /// 加载插件依赖的托管程序集
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        protected override Assembly Load(AssemblyName assemblyName)
        {
            string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
            
            //判断是否已经全局加载，如果全局加载，本插件再次加载，将仅使用本插件加载
            //的依赖库，不会使用全局加载的依赖库，有可能导致通过反射创建对象时，
            //创建对象同主框架对象不一致
            if (GlobalContext.defaultAssemblies.ContainsKey(assemblyName.FullName))
            {
                return null;
            }

            //判断本插件是否已经加载，如果已经加载，避免
            /*if (loadAssemblies.ContainsKey(assemblyName.FullName))
            {
                return null;
            }*/
            
            if (assemblyPath != null)
            {
                return LoadFromAssemblyPath(assemblyPath);
            }

            return null;
        }
        
        /// <summary>
        /// 加载插件依赖的非托管程序集
        /// </summary>
        /// <param name="unmanagedDllName"></param>
        /// <returns></returns>
        protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
        {
            string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
            if (libraryPath != null)
            {
                return LoadUnmanagedDllFromPath(libraryPath);
            }

            return IntPtr.Zero;
        }
    }
}
